package com.way.capture.activity;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.app.ShareCompat;
import androidx.core.app.SharedElementCallback;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import android.transition.Transition;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.ImageView;

import com.way.capture.R;
import com.way.capture.adapter.ItemAdapter;
import com.way.capture.adapter.viewholder.ViewHolder;
import com.way.capture.base.BaseActivity;
import com.way.capture.data.DataInfo;
import com.way.capture.utils.AppUtil;
import com.way.capture.utils.ParallaxTransformer;
import com.way.capture.utils.RxView;
import com.way.capture.utils.SimpleTransitionListener;
import com.way.capture.utils.Utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import butterknife.BindView;
import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;


public class DetailsActivity extends BaseActivity {
    public static final String EXTRA_DATAS = "extra_datas";
    public static final String EXTRA_STARTING_POSITION = "extra_starting_item_position";
    private static final String TAG = "DetailsActivity";
    private static final String STATE_CURRENT_PAGE_POSITION = "state_current_page_position";
    @BindView(R.id.toolbar)
    Toolbar mToolbar;
    @BindView(R.id.pager)
    ViewPager mViewPager;
    @BindView(R.id.bottom_bar)
    View mBottomBar;
    private int mStartingPosition;
    private int mCurrentPosition;
    private ArrayList<DataInfo> mDatas;
    private boolean mIsFullScreenMode = true;
    private boolean isReturning;
    private DataInfo albumItem;
    private final SharedElementCallback sharedElementCallback = new SharedElementCallback() {
        @Override
        public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
            if (isReturning) {
                ViewGroup v = mViewPager.findViewWithTag(albumItem.path);
                View sharedElement = v.findViewById(R.id.image);
                if (sharedElement == null) {
                    names.clear();
                    sharedElements.clear();
                } else {
                    names.clear();
                    names.add(sharedElement.getTransitionName());
                    sharedElements.clear();
                    sharedElements.put(sharedElement.getTransitionName(), sharedElement);
                }
            }
        }
    };
    private final SimpleTransitionListener transitionListener = new SimpleTransitionListener() {
        @Override
        public void onTransitionStart(@NonNull Transition transition) {
            //hide toolbar & statusbar
            float toolbarTranslationY = -(mToolbar.getHeight());
            mToolbar.setTranslationY(toolbarTranslationY);
            float bottomBarTranslationY = mBottomBar.getHeight();
            mBottomBar.setTranslationY(bottomBarTranslationY);
            super.onTransitionStart(transition);
        }

        @Override
        public void onTransitionEnd(@NonNull Transition transition) {
            ViewHolder viewHolder = ((ItemAdapter)
                    mViewPager.getAdapter()).findViewHolderByTag(albumItem.path);
            if (viewHolder == null) {
                return;
            }

            if (!isReturning) {
                viewHolder.onSharedElementEnter();
            }

            super.onTransitionEnd(transition);
            albumItem.isSharedElement = false;
            showUI(!isReturning);
        }
    };
    private boolean enterTransitionPostponed = false;

    public static void start(Context context, View view, ArrayList<DataInfo> urls, int position) {
        Intent intent = new Intent(context, DetailsActivity.class);
        intent.putExtra(EXTRA_DATAS, urls);
        intent.putExtra(EXTRA_STARTING_POSITION, position);
        ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
                (Activity) context, view, urls.get(position).path);
        ActivityCompat.startActivity(context, intent, options.toBundle());
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            postponeEnterTransition();
        }
        setEnterSharedElementCallback(sharedElementCallback);
        getWindow().getSharedElementEnterTransition().addListener(transitionListener);

        Intent intent = getIntent();
        mDatas = (ArrayList<DataInfo>) intent.getSerializableExtra(EXTRA_DATAS);
        mStartingPosition = intent.getIntExtra(EXTRA_STARTING_POSITION, 0);
        albumItem = mDatas.get(mStartingPosition);
        albumItem.isSharedElement = true;
        if (savedInstanceState != null) {
            mCurrentPosition = savedInstanceState.getInt(STATE_CURRENT_PAGE_POSITION, 0);
        } else {
            mCurrentPosition = mStartingPosition;
        }

        if (Utils.isNotch) {
            WindowManager.LayoutParams lp = getWindow().getAttributes();
            lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams
                    .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
            getWindow().setAttributes(lp);
        }
        initToolbar();
        initViewPager();
        setWindowInsets();
        getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_IMMERSIVE);
        mSubscriptions.add(RxView.clicks(findViewById(R.id.info_button))
                .throttleFirst(1000L, TimeUnit.MILLISECONDS)
                .flatMap((Function<View, ObservableSource<String>>) o
                        -> Observable.create((ObservableOnSubscribe<String>) emitter -> {
                    DataInfo dataInfo = mDatas.get(mCurrentPosition);
                    emitter.onNext(AppUtil.getDetails(DetailsActivity.this, dataInfo, dataInfo.type));
                    emitter.onComplete();
                }).subscribeOn(Schedulers.io())).observeOn(AndroidSchedulers.mainThread())
                .subscribe(s -> {
                    Log.d(TAG, "info button click: onSucceed: " + s);
                    AlertDialog.Builder builder = new AlertDialog.Builder(DetailsActivity.this);
                    builder.setTitle(R.string.image_info).setMessage(s).setPositiveButton(android.R.string.ok, null);
                    builder.create().show();
                }, throwable -> Log.e(TAG, "info button click onError: ", throwable)));
        mSubscriptions.add(RxView.clicks(findViewById(R.id.share_button))
                .throttleFirst(1000L, TimeUnit.MILLISECONDS)
                .map(v -> {
                    Drawable d = ((ImageView) v).getDrawable();
                    if (d instanceof Animatable) {
                        ((Animatable) d).start();
                    }
                    return v;
                })
                .flatMap((Function<View, ObservableSource<Uri>>) o
                        -> Observable.create((ObservableOnSubscribe<Uri>) emitter -> {
                    DataInfo dataInfo = mDatas.get(mCurrentPosition);
                    emitter.onNext(AppUtil.getContentUri(DetailsActivity.this, dataInfo.type, dataInfo.path));
                    emitter.onComplete();
                }).subscribeOn(Schedulers.io())).observeOn(AndroidSchedulers.mainThread())
                .subscribe(uri -> {
                    Log.d(TAG, "share button click: onSucceed: " + uri);
                    Intent shareIntent = ShareCompat.IntentBuilder.from(this)
                            .addStream(uri)
                            .setType(AppUtil.getMimeType(this, uri))
                            .getIntent();

                    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    if (shareIntent.resolveActivity(getPackageManager()) != null) {
                        startActivity(Intent.createChooser(shareIntent, null));
                    } else {
                        //Toast.makeText(this, error, Toast.LENGTH_SHORT).show();
                    }
                }, throwable -> Log.e(TAG, "share button click onError: ", throwable)));
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setWindowInsets();
    }

    private void setWindowInsets() {
        final ViewGroup rootView = findViewById(R.id.root_view);
        rootView.setOnApplyWindowInsetsListener((view, insets) -> {
            mToolbar.setPadding(insets.getSystemWindowInsetLeft(),
                    insets.getSystemWindowInsetTop(),
                    insets.getSystemWindowInsetRight(),
                    0);

            mBottomBar.setPadding(insets.getSystemWindowInsetLeft() + Utils.dp2px(8),
                    Utils.dp2px(8),
                    insets.getSystemWindowInsetRight() + Utils.dp2px(8),
                    insets.getSystemWindowInsetBottom() + Utils.dp2px(8));

            // clear this listener so insets aren't re-applied
            rootView.setOnApplyWindowInsetsListener(null);
            return insets.consumeSystemWindowInsets();
        });
    }

    private void showUI(boolean show) {
        float toolbarTranslationY = show ? 0 : -(mToolbar.getHeight());
        mToolbar.animate()
                .translationY(toolbarTranslationY)
                .setInterpolator(new AccelerateDecelerateInterpolator())
                .start();

        float bottomBarTranslationY = show ? 0
                : mBottomBar.getHeight();
        mBottomBar.animate()
                .translationY(bottomBarTranslationY)
                .setInterpolator(new AccelerateDecelerateInterpolator())
                .start();
    }

    private void showSystemUI(final boolean show) {
        runOnUiThread(() -> getWindow().getDecorView().setSystemUiVisibility(show ?
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_IMMERSIVE :
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                        | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                        | View.SYSTEM_UI_FLAG_IMMERSIVE
                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY));
        showUI(show);
    }

    @Override
    public void onBackPressed() {
        showUI(false);
        if (mViewPager != null && mViewPager.getAdapter() != null && albumItem != null) {
            ViewHolder viewHolder = ((ItemAdapter)
                    mViewPager.getAdapter()).findViewHolderByTag(albumItem.path);
            if (viewHolder != null) {
                viewHolder.onSharedElementExit(() -> setResultAndFinish());
            }
        }
    }

    public void setResultAndFinish() {
        isReturning = true;
        Intent data = new Intent();
        data.putExtra(MainActivity.ALBUM_PATH, mDatas);
        data.putExtra(MainActivity.EXTRA_CURRENT_ALBUM_POSITION, mViewPager.getCurrentItem());
        setResult(RESULT_OK, data);
        ActivityCompat.finishAfterTransition(this);
    }

    @Override
    protected int getContentView() {
        return R.layout.activity_details;
    }

    private void initToolbar() {
        setSupportActionBar(mToolbar);
        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }
    }

    private void initViewPager() {
        mViewPager.setAdapter(new ItemAdapter(mDatas));
        mViewPager.setCurrentItem(mCurrentPosition);
        mViewPager.setPageTransformer(true, new ParallaxTransformer());
        mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                mCurrentPosition = position;

                albumItem = mDatas.get(position);
                ViewHolder viewHolder = ((ItemAdapter) mViewPager.getAdapter())
                        .findViewHolderByTag(albumItem.path);
                if (viewHolder != null) {
                    viewHolder.onSharedElementEnter();
                }
            }
        });
        if (!enterTransitionPostponed()) {
            albumItem.isSharedElement = false;
            //there is no sharedElementTransition
            ItemAdapter adapter = (ItemAdapter) mViewPager.getAdapter();
            ViewHolder viewHolder = adapter.findViewHolderByTag(albumItem.path);
            if (viewHolder != null) {
                viewHolder.onSharedElementEnter();
            } else {
                ((ItemAdapter) mViewPager.getAdapter())
                        .addOnInstantiateItemCallback(viewHolder1 -> {
                            if (viewHolder1.mDataInfo.path.equals(albumItem.path)) {
                                viewHolder1.onSharedElementEnter();
                                return false;
                            }
                            return true;
                        });
            }
        }
    }

    @Override
    public void postponeEnterTransition() {
        enterTransitionPostponed = true;
        super.postponeEnterTransition();
    }

    @Override
    public void startPostponedEnterTransition() {
        enterTransitionPostponed = false;
        super.startPostponedEnterTransition();
    }

    boolean enterTransitionPostponed() {
        return enterTransitionPostponed;
    }

    public void toggleSystemUI() {
        mIsFullScreenMode = !mIsFullScreenMode;
        showSystemUI(mIsFullScreenMode);
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(STATE_CURRENT_PAGE_POSITION, mCurrentPosition);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    public interface Callback {
        void done();
    }

    public interface ViewPagerOnInstantiateItemCallback {
        boolean onInstantiateItem(ViewHolder viewHolder);
    }
}
